package com.order.app;

import cn.hutool.core.lang.UUID;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author xiangminwen
 * @date 2024/11/25 16:21
 */
public class LockBasedQueue3 {

    private final static ReentrantLock lock = new ReentrantLock();
    //容器满了信号
    private final static Condition full = lock.newCondition();
    //容器空了信号
    private final static Condition empty = lock.newCondition();
    //容器
    private final static List<String> breads = new ArrayList<>();
    //容器最大容量
    private final static int maxSize = 10;
    //计数器
    private final static AtomicInteger count = new AtomicInteger(0);

    public static void main(String[] args) {
        Thread producerThread = new Thread(new Producer());
        producerThread.setName("生产者1");
        producerThread.start();

        Thread producerThread1 = new Thread(new Producer());
        producerThread1.setName("生产者2");
        producerThread1.start();

        Thread consumerThread = new Thread(new Consumer());
        consumerThread.setName("消费者1");
        consumerThread.start();

        Thread consumerThread2 = new Thread(new Consumer());
        consumerThread2.setName("消费者2");
        consumerThread2.start();

    }


    static class Producer implements Runnable {

        //生产面包
        public void produce() {
            lock.lock();
            try {
                //如果容器满了，等待
                if (breads.size() == maxSize) {
                    //当前线程等待
                    full.await();
                }
                String bread = UUID.randomUUID() + "-" + Thread.currentThread().getName() + "-" + count.getAndIncrement();
                breads.add(bread);
                System.out.println(Thread.currentThread().getName() + "生产了面包：" + bread);
                //唤醒等待的消费者
                empty.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }

        @Override
        public void run() {
            while (true) {
                produce();
            }
        }
    }

    static class Consumer implements Runnable {

        //生产面包
        public void consumer() {
            lock.lock();
            try {
                if (breads.isEmpty()) {
                    empty.await();
                }
                String bread = breads.remove(0);
                System.out.println(Thread.currentThread().getName() + ":" + bread);
                full.signalAll();
                Thread.sleep(500);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }

        @Override
        public void run() {
            while (true) {
                consumer();
            }
        }
    }
}
